﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Medianamik.Core;
using Medianamik.Globalization;
using Medianamik.UI.Web.MVP.View;
using Medianamik.Core.Sugar;

namespace Medianamik.UI.Web.MVP.Presentation
{
    public abstract class NodeTypePropertyEditModulePresenter<TView>: ModulePresenter<TView>
        where TView : class, INodeTypePropertyEditModuleView
    {
        public virtual string ReturnUrl
        {
            get { return View.QueryString.GetValue<string>(DefaultParamNames.ReturnURL) != null
                            ? View.QueryString.GetValue<string>(DefaultParamNames.ReturnURL).DecodeBase64()
                            : null; }
        }

        public bool IsEdition
        {
            get { return PropertyId != null; }
        }

        public virtual Guid? TypeId
        {
            get
            {
                return View.QueryString.GetValue<Guid?>(DefaultParamNames.TypeID);
            }
        }

        public virtual Guid? PropertyId
        {
            get
            {
                return View.QueryString.GetValue<Guid?>(DefaultParamNames.PropertyId);
            }
        }

        protected virtual bool IncludeBaselookupNodeType { get { return false; } }

        protected virtual Guid? BaseLookupNodeType { get { return null; } }

        protected NodeTypePropertyEditModulePresenter(TView view)
            : base(view)
        {
        }

        protected override void Initialize(object sender, EventArgs e)
        {
            if (TypeId == null)
            {
                if (ReturnUrl == null)
                    throw new ApplicationException("TypeId and ReturnUrl are null");
                View.Redirect(ReturnUrl);
            }

            base.Initialize(sender, e);

            View.OnSave += OnNodeTypePropertySave;

            if(!View.IsPostBack)
            {
                if (View.CancelButton != null)
                {
                    View.CancelButton.NavigateUrl = ReturnUrl;
                }

                View.LookupNodeTypes = GetLookupNodeTypes();
                View.DataTypes = PropertyDefinitions.Definitions;
                View.ValidationExpression = PropertyValidationExpressions.Expressions;

                if(IsEdition)
                {
                    SetValues();
                }
            }
        }

        protected virtual List<NodeType> GetLookupNodeTypes()
        {
            if (BaseLookupNodeType == null)
                return new List<NodeType>();

            var baseType = NodeTypeManager.GetNodeType(BaseLookupNodeType.Value);
            var typeCollection = NodeTypeManager.GetAllChildTypes(BaseLookupNodeType.Value);
            if (baseType != null && IncludeBaselookupNodeType)
                typeCollection.Add(baseType);

            return typeCollection;
        }

        protected virtual void SetValues()
        {
            //var currentType = NodeTypeManager.GetNodeType(View.TypeId.Value);

            //View.NodeTypeNameValuesByCulture = Translator.GetResources("TypeManagement",
            //        currentType.ID + "_TypeName",
            //        ConfigManager.GetMedianamikCultures().Select(c => c.CultureInfo));;
            //View.IconPath = currentType.IconPath;
            //View.CanHaveChildren = currentType.IsInheritable;
            //View.IsGenerated = currentType.IsGenerated;
            //View.IsAbstract = currentType.IsAbstract;
            //View.IsListable = currentType.Listable;
            //View.IsVersioned = currentType.IsVersioned;
        }

        protected virtual NodeTypeProperty NewNodeTypeProperty(NodeType type)
        {
            var definition = PropertyDefinitions.Definitions.First(d => d.Id == View.SelectedDataType);

            Guid? primaryTypeId = null;
            Guid? primaryPropertyId = null;
            Guid? medianamikControlId = null;
            MedianamikControlInfo? medianamikControlInfo = null;
            Guid? primaryDataTypeId = null;

            bool hasRelationship = false;
            var relationship = NodeTypePropertyRelationship.Default;
            if(definition.Id == PropertyDefinitions.OneToManyPropertyId)
            {
                relationship = NodeTypePropertyRelationship.OneToMany;
                hasRelationship = true;
            }
            else if (definition.Id == PropertyDefinitions.ManyToOnePropertyId)
            {
                relationship = NodeTypePropertyRelationship.ManyToOne;
                hasRelationship = true;
            }

            if(hasRelationship)
            {
                var lookupType = NodeTypeManager.GetNodeType(View.SelectedLookup);
                if(lookupType == null)
                    throw new ApplicationException(string.Format("Type id {0} (INodeTypePropertyEditModuleView.SelectedLookup) could not be found", View.SelectedLookup));

                primaryTypeId = lookupType.ID;

                // Conventions: Name
                var primaryProp = lookupType.Properties.FirstOrDefault(p => p.Name == "Name");
                if(primaryProp == null)
                    throw new ApplicationException(string.Format("Could not find any usable default lookup property on type {0}", lookupType.Name));

                primaryPropertyId = primaryProp.ID;
                medianamikControlId = definition.MedianamikControlId;
                medianamikControlInfo = definition.MedianamikControlInfo;
                primaryDataTypeId = definition.DataTypeId;
            }

            short? maxLength = null;
            short? minLength = null;

            if(definition.DataTypeId == DataTypes.Varchar)
            {
                maxLength = View.MaxLength;
                minLength = View.MinLength;
            }

            Regex validationRegex = null;
            if(!string.IsNullOrEmpty(View.SelectedValidationExpression))
                validationRegex = new Regex(View.SelectedValidationExpression);

            var property = type.AddProperty(GetNodeTypePropertyName(),
                   maxLength,
                   minLength,
                   false,  // haveTooltip
                   !View.ValuesAreLocalized,
                   false,  // allowNulls
                   false,   // isUnique
                   validationRegex,   // validationRegex
                   "Content",
                   definition.MedianamikControlId,
                   definition.MedianamikControlInfo,
                   definition.DataTypeId,
                   primaryTypeId,   // primaryTypeID
                   primaryPropertyId,   // primaryMedianamikControlID
                   medianamikControlId,   // primaryMedianamikControlSettings
                   medianamikControlInfo,   // primaryDataTypeId
                   primaryDataTypeId,
                   null    // treeRootNodeId
               );
            property.IsRequired = View.IsRequired;
            property.IsGenerated = false;
            property.Relationship = relationship;

            return property;
        }

        protected void OnNodeTypePropertySave(object sender, EventArgs e)
        {
            if (IsEdition)
            {
                UpdateNodeTypeProperty();
            }
            else
            {
                SaveNodeTypeProperty();
            }
            View.Redirect(ReturnUrl);
        }

        protected virtual void UpdateNodeTypeProperty()
        {
            //Translator.CreateResource("TypeManagement", View.TypeId + "_TypeName", View.NodeTypeNameValuesByCulture);
        }

        protected virtual void SaveNodeTypeProperty()
        {
            var type = NodeTypeManager.GetNodeType(TypeId.Value);

            var property = NewNodeTypeProperty(type);

            NodeTypeManager.SaveType(type);

            Translator.CreateResource("TypeManagement", property.ID + "_Label", View.NodeTypePropertyNameValuesByCulture);
        }

        protected virtual string GetNodeTypePropertyName()
        {
            var name = View.NodeTypePropertyNameValuesByCulture.ContainsKey("en-CA")
                ? View.NodeTypePropertyNameValuesByCulture["en-CA"]
                : View.NodeTypePropertyNameValuesByCulture.First().Value;

            return name.ToCodeSafe();
        }
    }
}